package com.ruoyi.common.core.utils;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.ruoyi.common.core.annotation.DataTranslator;
import com.ruoyi.common.core.enums.TranslatorConstants;

import java.io.IOException;
import java.util.Objects;

public class DataTranslatorSerializer extends JsonSerializer<String> implements ContextualSerializer {

    /**
     * 翻译类型
     */
    private TranslatorConstants type;

    /**
     * 翻译结果指定的属性
     */
    private String fieldName;

    /**
     * 额外的参数
     */
    private String[] args;


    public DataTranslatorSerializer(TranslatorConstants type, String fieldName, String[] args) {
        this.type = type;
        this.fieldName = fieldName;
        this.args = args;
    }

    /**
     * Method that can be called to ask implementation to serialize
     * values of type this serializer handles.
     *
     * @param s       Value to serialize; can <b>not</b> be null.
     * @param jsonGenerator         Generator used to output resulting Json content
     * @param serializerProvider Provider that can be used to get serializers for
     */
    @Override
    public void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {

        // 根据注解的内容，分别处理具体的值
        // s -- 注解所在属性的属性值

        // 给对象添加属性 fieldName，属性的值就是 属性值
        jsonGenerator.writeStringField(fieldName, "给对象设置的属性值");

    }

    /**
     * Method called to see if a different (or differently configured) serializer
     * is needed to serialize values of specified property.
     * Note that instance that this method is called on is typically shared one and
     * as a result method should <b>NOT</b> modify this instance but rather construct
     * and return a new instance. This instance should only be returned as-is, in case
     * it is already suitable for use.
     *
     * @param serializerProvider     Serializer provider to use for accessing config, other serializers
     * @param beanProperty Method or field that represents the property
     *                 (and is used to access value to serialize).
     *                 Should be available; but there may be cases where caller cannot provide it and
     *                 null is passed instead (in which case impls usually pass 'this' serializer as is)
     * @return Serializer to use for serializing values of specified property;
     * may be this instance or a new instance.
     * @throws JsonMappingException
     */
    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
        if (beanProperty != null) {
            // 非String直接跳过
            if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
                // 获取注解对象
                DataTranslator dataTranslator = beanProperty.getAnnotation(DataTranslator.class);
                if (dataTranslator == null) {
                    dataTranslator = beanProperty.getContextAnnotation(DataTranslator.class);
                }
                // 如果能得到注解，就获取注解的值，留存下一步使用
                if (dataTranslator != null) {
                    return new DataTranslatorSerializer(dataTranslator.type(), dataTranslator.fieldName(), dataTranslator.args());
                }
            }
            return serializerProvider.findKeySerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(null);
    }
}
